package dao.hibernate;

import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import dao.IDaoRef;
import service.configuration.IConfiguration;
import service.configuration.NamingUtil;
import entities.LinkAssociation;
import entities.OwnerAssociation;
import entities.SmallSheet;
import entities.TreeAssociation;


@Service
@Lazy
public class DaoHibernateRef extends DaoHibernate implements IDaoRef {

	@Autowired
	public DaoHibernateRef(HibernateUtilRef hibernateUtil, SheetFactory sheetFactory,
			IConfiguration config) {
	
		super(hibernateUtil, sheetFactory, config);
	}


	public List<SmallSheet> findAllSmallSheets(String type) {
		Session session = hibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		
		try {
			transaction = session.beginTransaction();
			
			@SuppressWarnings("unchecked")
			List<SmallSheet> result = session.createCriteria(type)
			.addOrder(Order.asc(NamingUtil.CODE))
			.setProjection(Projections.projectionList()
					.add(Projections.property(NamingUtil.CODE), "code")
					.add(Projections.property(NamingUtil.VERSION), "version"))
			.setResultTransformer(Transformers.aliasToBean(SmallSheet.class) )
			.list();
					
			return result;
		} catch(HibernateException e) {
			transaction.rollback();
			throw e;
		} finally {
			session.close();
		}
	}
	


	public List<OwnerAssociation> findOwnerAssociations(String query, String sheetType) {	
		Session session = hibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
				
		try {
			transaction = session.beginTransaction();		
			ScrollableResults results = session.createSQLQuery(query).scroll();
			
			List<OwnerAssociation> associations = new ArrayList<OwnerAssociation>();
			while(results.next()) {
				associations.add(new OwnerAssociation((String)results.get(0),
													  (String)results.get(1),
													  sheetType));						  
			}
					
			return associations;
		} catch(HibernateException e) {
			transaction.rollback();
			throw e;
		} finally {
			session.close();
		}
	}



	@Override
	public List<TreeAssociation> findTreeAssociations(String query,
			String fromType, String toType) {

		Session session = hibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		
		try {
			transaction = session.beginTransaction();		
			ScrollableResults results = session.createSQLQuery(query).scroll();
			
			List<TreeAssociation> associations = new ArrayList<TreeAssociation>();
			while(results.next()) {
				associations.add(new TreeAssociation((String)results.get(0),
													 (String)results.get(1),
													 fromType,
													 toType,
													 results.getRowNumber()));						  
			}
					
			return associations;
		} catch(HibernateException e) {
			transaction.rollback();
			throw e;
		} finally {
			session.close();
		}
	}



	@Override
	public List<LinkAssociation> findLinkAssociations(String query,
			String fromType, String toType, String label) {
		Session session = hibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		
		try {
			transaction = session.beginTransaction();		
			ScrollableResults results = session.createSQLQuery(query).scroll();
			
			List<LinkAssociation> associations = new ArrayList<LinkAssociation>();
			while(results.next()) {
				associations.add(new LinkAssociation((String)results.get(0),
													 (String)results.get(1),
													 fromType,
													 toType,
													 label,
													 results.getRowNumber()));						  
			}
					
			return associations;
		} catch(HibernateException e) {
			transaction.rollback();
			throw e;
		} finally {
			session.close();
		}
	}
}
